import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import {
  FetchKeywordType,
  KeywordType,
  KeywordWithCollectionType,
  KeywordWithName,
} from "../domain/keyword";
import { keywordApi } from "../backend/server";
import { action } from "../../views/Functions/children/Collections/Collections";
import { copyText } from "../common/copy";
import _ from "lodash";
import { CollectionType } from "../domain/CollectionType";
import { store } from "./store";

const collectionList: KeywordWithName[] = [];
const keyword: string = "";
const pageNo: number = 1;
const pageSize: number = -1;
const total: number = 0;
const filterList: CollectionType[] = [];

/**
 {
      id: -1,
      typeName: "",
      description: "",
      createTime: "",
    }
 */

const modalInfo: {
  open: boolean;
  type: action;
  item: KeywordType & { isTemp?: boolean } & {
    collectionType: CollectionType | null;
  };
} = {
  open: false,
  type: "",
  item: {
    id: "",
    keyName: "",
    ranks: 0,
    url: "",
    memo: "",
    isTemp: true,
    collectionType: null,
    // name: "",
    // collectionType: ,
  },
};

const collectionTypeModal: CollectionType & {
  showModal: boolean;
  belong: null | string;
} = {
  id: -1,
  typeName: "",
  description: "",
  createTime: "",
  showModal: false,
  belong: null,
};

export const collectionSlice = createSlice({
  name: "collection",
  initialState: {
    keyword,
    collectionList,
    filterList,
    pageSize,
    pageNo,
    total,
    modalInfo,
    collectionTypeModal,
  },
  reducers: {
    addFilter: (state, action: PayloadAction<CollectionType[]>) => {
      const removeExist: CollectionType[] = [];
      state.filterList.forEach((exist) => {
        if (action.payload.find((item) => item.id === exist.id)) return;
        removeExist.push(exist);
      });

      return {
        ...state,
        filterList: [...removeExist, ...action.payload],
      };
    },
    removeFilterById: (state, action: PayloadAction<CollectionType[]>) => {
      const filterList: CollectionType[] = state.filterList.filter((filter) =>
        action.payload.find((item) => item.id !== filter.id)
      );

      return {
        ...state,
        filterList,
      };
    },
    updateKeyword: (state, action: PayloadAction<string>) => {
      return {
        ...state,
        keyword: action.payload,
      };
    },
    nextPage: (state, action: PayloadAction<number>) => {
      return {
        ...state,
        pageNo: action.payload,
      };
    },
    updatePageSize: (state, action: PayloadAction<number>) => {
      return {
        ...state,
        pageSize: Math.min(action.payload, 100),
      };
    },
    // updateModalType: (
    //   state,
    //   action: PayloadAction<(typeof modalInfo)["type"]>
    // ) => {
    //   return {
    //     ...state,
    //     modalInfo: {
    //       ...modalInfo,
    //       type: action.payload,
    //     },
    //   };
    // },
    updateModal: (
      state,
      action: PayloadAction<typeof modalInfo | undefined>
    ) => {
      return {
        ...state,
        modalInfo: action.payload || modalInfo,
      };
    },
    // Partial<typeof collectionTypeModal> & { belong: string }
    cleanCollectionTypeModal(state, action: PayloadAction<undefined>) {
      return {
        ...state,
        collectionTypeModal: {
          showModal: false,
          belong: null,
          id: -1,
          typeName: "",
          description: "",
          createTime: "",
        },
      };
    },
    updateCollectionTypeModal(
      state,
      action: PayloadAction<
        | ({ showModal: true; belong: string } & Partial<CollectionType>)
        | ({ showModal: false } & Partial<CollectionType>)
      >
    ) {
      return {
        ...state,
        collectionTypeModal: {
          ..._.cloneDeep(state.collectionTypeModal),
          ...action.payload,
        },
      };
    },
    updateModalItem: (
      state,
      action: PayloadAction<Partial<(typeof modalInfo)["item"]> | undefined>
    ) => {
      const obj = _.cloneDeep(state.modalInfo);
      obj.item = { ...obj.item, ...action.payload };
      return {
        ...state,
        modalInfo: obj || modalInfo,
      };
    },
  },
  extraReducers: (builders) => {
    builders.addCase(fetchCollectionById.fulfilled, (state, action) => {
      state.modalInfo = {
        ...state.modalInfo,
        open: true,
        item: action.payload,
        type: "modify",
      };
    });
    builders.addCase(fetchCollectionList.rejected, (state, action) => {
      copyText(JSON.stringify(action));
    });
    builders.addCase(fetchCollectionList.fulfilled, (state, action) => {
      const res = action.payload;
      state.collectionList = extractName(res.list);
      state.total = res.total;
      state.pageNo = res.pageNo;
    });
  },
});

export const fetchCollectionById = createAsyncThunk<
  KeywordWithCollectionType,
  KeywordType["id"],
  {
    state: ReturnType<typeof store.getState>;
  }
>("collection/fetchKeywordById", async (param, action) => {
  return await keywordApi.fetchPlaceholder(param).getData();
});
// Partial<{
//   search: string;
//   pageNo: number;
//   pageSize: number;
// }>
export const fetchCollectionList = createAsyncThunk<
  FetchKeywordType,
  void,
  { state: ReturnType<typeof store.getState> }
>("collection/fetchCollectionList", async (_, { getState }) => {
  const {
    keyword: search,
    pageNo,
    pageSize,
    filterList,
  } = getState().collection;
  return await keywordApi.fetchPlaceholders({
    search,
    filterList,
    pageNo,
    pageSize,
  });
});

export const collectionReducer = collectionSlice.reducer;

export const extractName = (val: KeywordType[]): KeywordWithName[] => {
  const arr = val.map((val) => ({
    ...val,
    keyName: val.keyName,
    name: val.url
      .replace(/(http:\/\/|https:\/\/|www)\.{0,1}/g, "")
      .substring(0, 5),
  })) as KeywordWithName[];
  // .sort(
  //   (a, b) => a.keyName.charCodeAt(0) - b.keyName.charCodeAt(0)
  // ) as KeywordWithName[];

  return arr;
  // let sortInx = 0;
  // let sortByName: KeywordWithName[] = [];
  // for (let i = 0; i < arr.length; i++) {
  //   const ranks = arr[i].ranks;
  //   if (Number(ranks) === 0) {
  //     sortInx = i;
  //     sortByName = arr
  //       .slice(sortInx)
  //       .sort((a, b) => a.keyName.charCodeAt(0) - b.keyName.charCodeAt(0));
  //     break;
  //   }
  // }

  // return [...arr.slice(0, sortInx), ...sortByName];
};

export const {
  updateModal,
  updateModalItem,
  updatePageSize,
  updateKeyword,
  updateCollectionTypeModal,
  addFilter,
  removeFilterById,
  cleanCollectionTypeModal,
  nextPage,
  // updateModalType,
} = collectionSlice.actions;
